package controllers

import (
	"beegoProject19/models/auth"
	"beegoProject19/utils"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"
	"math"
	"time"
)

type HomeController struct {
	beego.Controller
}

func (c *HomeController) Get() {

	o := orm.NewOrm()

	userId := c.GetSession("id")

	user := auth.User{
		Id: userId.(int),
	}
	o.LoadRelated(&user, "Role")

	authArr := []int{}
	for _, role := range user.Role {
		roleData := auth.Role{
			Id: role.Id,
		}
		o.LoadRelated(&roleData, "Auth")
		for _, authData := range roleData.Auth {
			authArr = append(authArr, authData.Id)
		}
	}

	qs := o.QueryTable("sys_auth")

	auths := []auth.Auth{}
	// 1 升序排列 .OrderBy("数据库字段")  / 降序 .OrderBy("-数据库字段")
	qs.Filter("pid", 0).Filter("id__in", authArr).OrderBy("-weight").All(&auths)

	trees := []auth.Tree{}

	for _, authData := range auths {
		pid := authData.Id
		treeData := auth.Tree{
			Id:       authData.Id,
			AuthName: authData.AuthName,
			UrlFor:   authData.UrlFor,
			Weight:   authData.Weight,
			Children: []*auth.Tree{},
		}
		GetChildNode(pid, &treeData)
		trees = append(trees, treeData)
	}

	o.QueryTable("sys_user").Filter("id", userId).One(&user)

	/*
		增加消息通知数据库保存 ----------------------------------------------------------
	*/
	// 1 查询车辆表
	qsCars := o.QueryTable("sys_cars_apply")

	// 2 消息存放位置
	carsApply := []auth.CarsApply{}

	// 3 查询当前登陆的用户信息,[Filter("return_status", 0]查询下是否已归还 , notify_tg 发送消息字段过滤出未发送的
	qsCars.Filter("user_id", userId.(int)).Filter("return_status", 0).Filter("notify_tag", 0).All(&carsApply)

	// 5 当前日期
	curTime, _ := time.Parse("2006-01-02", time.Now().Format("2006-01-02"))

	// 4 查询是否逾期 return_date字段
	for _, apply := range carsApply {
		returnDate := apply.ReturnDate
		// 6 用当前时间减去逾期时间
		ret := curTime.Sub(returnDate)
		// 如果当前时间大于逾期时间即表示逾期

		// 7 格式化content    returnDate需要格式化成 年月日
		content := fmt.Sprintf("%s用户,您借的车辆归还时间为%v,已逾期,请尽快归还!", user.UserName, returnDate.Format("2006-01-02"))

		// 8 大于0 则逾期
		if ret > 0 {
			// 逾期之后将数据填充到数据库
			messageNotify := auth.MessageNotify{
				Flag:    1,
				Title:   "车辆逾期",
				Content: content, // Content 需要先进行格式化
				User:    &user,
				ReadTag: 0, // 未读
			}
			// 9 数据库插入
			o.Insert(&messageNotify)
		}
		// 10 更新数据库已发送和未发送字段，消息之发送一次。
		apply.NotifyTag = 1
		o.Update(&apply)
	}
	/*
		增加消息通知 （websocket优化）----------------------------------------------------------
	*/

	/* 展示消息 ----------------------------------------------------------- */

	qs2 := o.QueryTable("sys_message_notify")
	// 展示未读信息
	notifyCount, _ := qs2.Filter("read_tag", 0).Count()

	c.Data["notify_count"] = notifyCount

	/* 展示消息 ----------------------------------------------------------- */

	c.Data["user"] = user
	c.Data["trees"] = trees
	c.TplName = "index.html"
}

func (c *HomeController) Welcome() {
	c.TplName = "welcome.html"
}

// GetChildNode  6. 定义GetChildNode
func GetChildNode(pid int, treeNode *auth.Tree) {

	// 8.查询出全部的二级菜单，存入auths内
	o := orm.NewOrm()
	qs := o.QueryTable("sys_auth")
	auths := []auth.Auth{}
	_, err := qs.Filter("pid", pid).OrderBy("-weight").All(&auths)
	if err != nil {
		return
	}

	// 9. 循环auths继续查询三级及以上的菜单
	for i := 0; i < len(auths); i++ {
		pids := auths[i].Id // 根据pid获取所有子节点

		// 10. 初始化
		treeData := auth.Tree{
			Id:       auths[i].Id,
			AuthName: auths[i].AuthName,
			UrlFor:   auths[i].UrlFor,
			Weight:   auths[i].Weight,
			Children: []*auth.Tree{},
		}

		// 12. 追加写入Children
		treeNode.Children = append(treeNode.Children, &treeData)

		// 11. 调用 GetChildNode
		GetChildNode(pids, &treeData)
	}

	return
}

func (c *HomeController) NotifyList() {

	o := orm.NewOrm()
	qs := o.QueryTable("sys_message_notify")
	notifies := []auth.MessageNotify{}

	// 每页显示数据-4条 (pagePerNum)
	pagePerNum := 5

	var count int64 = 0

	// 当前页 (currentPage)
	currentPage, err := c.GetInt("page")

	/*
		增加查询：
	*/
	offsetNum := pagePerNum * (currentPage - 1)

	kw := c.GetString("kw")

	/* 查询日志 */
	ret := fmt.Sprintf("当前页:%d,查询条件:%s", currentPage, kw)
	logs.Info(ret)

	if kw != "" { // 判断kw有查询条件的，那就会对总数和用户查询结果有影响
		// 总数据量--增加过滤username__contains
		count, _ = qs.Filter("title__contains", kw).Count()
		// 用户详细信息查询--增加过滤username__contains
		qs.Filter("title__contains", kw).Limit(pagePerNum).Offset(offsetNum).All(&notifies)
	} else {
		// 总数据量
		count, _ = qs.Count()
		// 用户详细信息查询
		qs.Limit(pagePerNum).Offset(offsetNum).All(&notifies)
	}

	// 总页数 (count) =  总数据量 / 每页数据量   注：需要转换成int类型
	countPage := int(math.Ceil(float64(count) / float64(pagePerNum)))

	// err 当点击页面时候没有获取到当前页也就是null，所以默认显示第一页
	if err != nil {
		currentPage = 1
	}

	// 判断上一页
	prePage := 1
	if currentPage == 1 {
		prePage = currentPage
	} else if currentPage > 1 {
		// 上一页
		prePage = currentPage - 1
	}

	// 下一页
	nextPage := 1
	// 如果当前页小于总页数
	if currentPage < countPage {
		// 下一页 就等于 当前页+1
		nextPage = currentPage + 1
		// 如果当前页面大于等于总页数
	} else if currentPage >= countPage {
		// 下一页 就等于 当前页
		nextPage = currentPage
	}

	// 引用倒入到函数page.go
	pageMap := utils.Paginator(currentPage, pagePerNum, count)

	c.Data["page_map"] = pageMap
	c.Data["notifies"] = notifies
	c.Data["prePage"] = prePage         /* 上一页*/
	c.Data["nextPage"] = nextPage       /* 下一页 */
	c.Data["currentPage"] = currentPage /* 当前页 */
	c.Data["countPage"] = countPage     /* 总页数 */
	c.Data["count"] = count
	c.Data["kw"] = kw

	c.TplName = "notify-list.html"

}

func (c *HomeController) ReadNotify() {
	/* 当用户点击之后获取用户ID去修改数据库字段 */
	id, _ := c.GetInt("id")
	o := orm.NewOrm()
	qs := o.QueryTable("sys_message_notify")
	qs.Filter("id", id).Update(orm.Params{
		"read_tag": 1,
	})
	c.Redirect(beego.URLFor("HomeController.NotifyList"), 302)
}
